home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CRYP60.ZIP / CRYP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-15  |  17.2 KB  |  585 lines

  1. #include <stdlib.h> /* defines exit() and malloc()                       */
  2. #include <fcntl.h>  /* defines "open flags" O_BINARY, ...                */
  3. #include <io.h>     /* defines setmode()                                 */
  4. #include <string.h> /* defines strlen etc.                               */
  5. #include <stdio.h>  /* defines NULL, EOF, stdin, stdout, stderr,         */
  6.             /* fprintf(), fileno(), ... for standard i/o         */
  7.  
  8. extern int errno;
  9.  
  10. char  name[]  = "CRYP - A data encryption system written in C, with pipes";
  11. char  version[] = "Version 6.00, 1992-11-15, 1400 hours";
  12. char  author[]  = "Copyright (c) 1987-1992 by author: Harry J. Smith";
  13. char  address[] =
  14.       "19628 Via Monte Dr., Saratoga, CA 95070.  All rights reserved.";
  15.  
  16. char  usage1[]  =  "usage: CRYP key [D/I] [<infile] [>outfile]";
  17. char  usage2[]  =  "  D = Decipher";
  18. char  usage3[]  =  "  I = Init CRY.CON file using key and exit";
  19. char  usage4[]  =  "  default = Encipher and update CRY.CON file";
  20.  
  21. #define  POOLSIZE 2048         /* Number of integers in random number pool */
  22. #define  CONSIZE  18         /* Number of characters in CRY.CON file       */
  23. #define  BUFSIZE  16384         /* Number of characters in file i/o buffer     */
  24. #define  MAXKEY   24         /* Number of characters in short key     */
  25. #define  TRUE     1
  26. #define  FALSE    0
  27.  
  28. int  ri[9];         /* Current random integers from the 9 generators     */
  29. int  rs[9];         /* Initial random seeds for the 9 generators         */
  30. int  rc[9];         /* Current value of clear continuation seeds         */
  31. int  rr;            /* Random running combination of ri[0] thru ri[8]    */
  32. int  *pool;         /* Pool of POOLSIZE random integers                  */
  33. char *buf;          /* Buffer for file i/o                               */
  34. char key[MAXKEY+1]; /* The short key string in standard form             */
  35. int  encipher;      /* Boolean, Enciphering a file, FALSE => Deciphering */
  36. int  next = 0;      /* Next random no. routine to use, cycles 0 thru 8   */
  37. int  poolmask =     /* Mask for index to random pool = 2**N - 1          */
  38.        POOLSIZE-1;
  39. int  in;            /* handle of input stream */
  40. int  out;           /* handle of output stream */
  41. FILE *confile;      /* File pointer of continuation file "CRY.CON"       */
  42. FILE *infile;       /* File pointer of input of key file                 */
  43.  
  44. int  init( int argc, char *argv[]);  /* Initialize the process           */
  45. int  term( void);                    /* Terminate processing             */
  46. void standard( char *cp);            /* Standardize a key string         */
  47. void convkey( void);                 /* Convert key to 9 seeds           */
  48. int  rn( int n);                     /* random integer from ri[n], n<9   */
  49. int  rc9( void);                     /* Combination of rn(0) thru rn(8)  */
  50. void erase( void);                   /* Erase all trace of the key       */
  51.  
  52. /* --------------------------------------------------------------------- */
  53. void main( int argc, char *argv[])
  54. {
  55.    int  *ip;                /* Pointer to current integer in buf         */
  56.    int  *jp;                /* Pointer after last integer in buf         */
  57.    int  ind;                /* Random index into pool of random integers */
  58.    int  nr;                 /* Number of bytes read into buf             */
  59.    int  rc;                 /* Return code from init() and term()        */
  60.  
  61.    if( argc < 2)
  62.    {
  63.       fprintf( stderr, "\n%s\n%s\n%s\n\n", name, version, author);
  64.       fprintf( stderr, "%s\n%s\n%s\n%s\n", usage1, usage2, usage3, usage4);
  65.       exit( 1);
  66.    }
  67.  
  68.    rc = init( argc, argv);                /* Initialize the process      */
  69.  
  70.    if( rc)
  71.    {                                      /* If error in init,           */
  72.       erase();                            /* erase key                   */
  73.       exit( rc);                          /* and exit                    */
  74.    }
  75.  
  76.    while ( (nr = fread( buf, 1, BUFSIZE, stdin)) != 0) /* read file      */
  77.    {
  78.       for( ip = (int *)buf, jp = ip + (nr+1)/2;   ip != jp;   ++ip)
  79.       {
  80.      /*
  81.       * This is the heart of the encryption method
  82.       */
  83.  
  84.      ind = rr & poolmask;             /* Random index to random pool */
  85.      *ip ^= pool[ ind];               /* XOR data with random int    */
  86.      pool[ ind] ^= (rr += rn( next)); /* XOR random int with next rr */
  87.      if( ++next == 9)                 /* Cycle to next generator     */
  88.         next = 0;
  89.       }
  90.  
  91.       if( fwrite( buf, 1, nr, stdout) != nr) /* Write file and test      */
  92.       {                                      /* If write error, exit     */
  93.      erase();
  94.      fprintf( stderr, "CRYP: write error no. %d\n", errno);
  95.      exit( 2);
  96.       }
  97.    }
  98.  
  99.    rc = term();                           /* Terminate processing        */
  100.    erase();                               /* Erase all trace of the key  */
  101.    fprintf( stderr, "return = %d\n", rc); /* Diagnostic, may be removed  */
  102.    exit( rc);                             /* Exit main                   */
  103. }
  104.                       /* End of main (CRYP)          */
  105.  
  106. /* --------------------------------------------------------------------- */
  107. int init( int argc, char *argv[])         /* Initialize the process      */
  108. {
  109.     /*  Initialize key etc.
  110.      *  Returns a non-zero flag if error
  111.      */
  112.  
  113.    int  i, j, len;
  114.    char *chp;
  115.  
  116.    buf  = malloc( BUFSIZE);               /* Allocate memory for arrays  */
  117.    pool = (int *) malloc( 2 * POOLSIZE);
  118.  
  119.    if( buf == (char *) NULL || pool == (int *) NULL)
  120.    {
  121.       fprintf( stderr, "CRYP: not enough memory\n");
  122.       return( 1);
  123.    }
  124.  
  125.    if( (infile = fopen( argv[1], "rt")) == NULL) /* Try to open key file */
  126.    {
  127.       strcpy(buf, argv[1]);
  128.       len = strlen( buf);
  129.       for( i = 0;  i < len;  ++i)
  130.      argv[1][i] = 0;          /* Erase input key         */
  131.    }
  132.    else
  133.    {
  134.       fgets( buf, 256, infile);
  135.       fclose( infile);
  136.       if( (chp = strchr( buf, '\n')) != NULL)
  137.      *chp = '\0';
  138.    }
  139.  
  140.    standard( buf);              /* Standardize long key     */
  141.  
  142.    fprintf( stderr, "%s = input key in standard form\n", buf);
  143.  
  144.    if( (len = strlen( buf)) > MAXKEY)
  145.    {
  146.       for( i = 1; i < MAXKEY; ++i)      /* Hash long key         */
  147.      buf[i] += buf[i-1];
  148.       for( i = len-2; i >= MAXKEY; --i)
  149.      buf[i] += buf[i+1];
  150.    }
  151.  
  152.    for( i = 0;  i <= MAXKEY;  ++i)      /* Clear short key         */
  153.       key[i] = 0;
  154.  
  155.    for( i = j = 0;  i < len;  ++i)      /* Compress long key         */
  156.    {
  157.       key[j] += buf[i];
  158.       buf[i] = 0;              /* Erase input key         */
  159.       if( ++j == MAXKEY)
  160.      j = 0;
  161.    }
  162.  
  163.    for( i = 0;  i < MAXKEY;  ++i)         /* Fill out key replacing      */
  164.       if( !key[i])                        /* nulls with spaces           */
  165.      key[i] = ' ';
  166.  
  167.    standard( key);                        /* Standardize short key       */
  168.    convkey();                             /* Convert short key to random */
  169.                       /* number seeds                */
  170.  
  171.    encipher = TRUE;                       /* Set default to encipher     */
  172.  
  173.    if( argc > 2)
  174.    {
  175.       if( *argv[2] == 'I' || *argv[2] == 'i')
  176.       {
  177.      if( (confile = fopen( "CRY.CON", "wb")) == NULL)
  178.      {
  179.         fprintf( stderr,
  180.            "CRYP: cannot open CRY.CON, error no. %d\n", errno);
  181.         return( 2);
  182.      }
  183.      for( i = 0;  i < 9;  ++i)        /* Initialize CRY.CON file     */
  184.         ri[i] = rs[i];
  185.  
  186.      for( i = POOLSIZE-1;  i >= 0;  --i) /* Build a random record     */
  187.         pool[i] = rc9();
  188.                       /* Write continuation file     */
  189.  
  190.      if( fwrite( pool, 1, CONSIZE, confile) != CONSIZE)
  191.      {
  192.         fprintf( stderr,
  193.            "CRYP: cannot write CRY.CON, error no. %d\n", errno);
  194.         return( 3);
  195.      }
  196.      fclose( confile);
  197.      fprintf( stderr, "Continuation file CRY.CON updated\n");
  198.      return( 4);
  199.       }
  200.       else                                /* Set encipher/decipher flag  */
  201.     encipher =  *argv[2] != 'D' && *argv[2] != 'd';
  202.    }
  203.  
  204.    in = fileno( stdin);  out = fileno( stdout);
  205.    if ( (setmode( in, O_BINARY)) == -1)   /* switch stdin to binary mode */
  206.    {  perror( "Binary mode not available for stdin\n");
  207.       free( buf);  return( 5);
  208.    }
  209.    if ( (setmode( out, O_BINARY)) == -1)  /* switch stdout to binary mode*/
  210.    {  perror( "Binary mode not available for stdout\n");
  211.       free( buf);  return( 6);
  212.    }
  213.  
  214.    if( encipher)                          /* Use CRY.CON and encipher    */
  215.    {
  216.       if( (confile = fopen( "CRY.CON", "rb")) == NULL)
  217.       {
  218.      fprintf( stderr,
  219.         "CRYP: cannot open CRY.CON, error no. %d\n", errno);
  220.      return( 7);
  221.       }
  222.  
  223.       if( fread( pool, 1, CONSIZE, confile) != CONSIZE)
  224.       {
  225.      fprintf( stderr,
  226.         "CRYP: cannot read CRY.CON, error no. %d\n", errno);
  227.      return( 8);
  228.       }
  229.       fclose( confile);
  230.                       /* Write 1st record of output  */
  231.  
  232.       if( fwrite( pool, 1, CONSIZE, stdout) != CONSIZE)
  233.       {
  234.      fprintf( stderr, "CRYP: write error no. %d\n", errno);
  235.      return( 9);
  236.       }
  237.    }
  238.    else                      /* Read first record of file   */
  239.    {
  240.       if( fread( pool, 1, CONSIZE, stdin) != CONSIZE)
  241.       {
  242.      fprintf( stderr, "CRYP: read error no. %d\n", errno);
  243.      return( 10);
  244.       }
  245.    }
  246.  
  247.    for( i = 0;  i < 9;  ++i)              /* Save and encode             */
  248.    {                                      /* continuation seeds          */
  249.       rc[i] = pool[i];
  250.       ri[i] = rs[i] ^ pool[i];
  251.       if( !ri[i])                         /* Do not allow a zero seed    */
  252.      ri[i] = 1;
  253.    }
  254.    rr = rc9();                            /* Init first word of running  */
  255.                       /* combination of ri[0]- ri[8] */
  256.  
  257.    for( i = 0;  i < POOLSIZE;  ++i)       /* Initialize pool, random int */
  258.    {
  259.       pool[i] = rr += rn( next);
  260.       if( ++next == 9)
  261.      next = 0;
  262.    }
  263.    rr = rc9();                            /* Init rr for first random    */
  264.                       /* index into pool             */
  265.  
  266.    fprintf( stderr, "%s = short key in standard form\n", key);
  267.  
  268.    for( i = 0;  i < 9;  ++i)
  269.       fprintf( stderr, "rs[%d] = %-7d ", i, rs[i]);
  270.  
  271.    for( i = 0;  i < 9;  ++i)
  272.       fprintf( stderr, "ri[%d] = %-7d ", i, ri[i]);
  273.  
  274.    if( encipher)
  275.       fprintf( stderr, "\nEncipher\n");
  276.    else
  277.       fprintf( stderr, "\nDecipher\n");
  278.  
  279.    return( 0);
  280. }                                         /* End of init                 */
  281.  
  282. /* --------------------------------------------------------------------- */
  283. int term( void)
  284. {
  285.     /*  Terminate processing
  286.      *  Returns a non-zero flag if error
  287.      */
  288.  
  289.    int  i;
  290.  
  291.    if( ferror( stdin))                    /* Test for infile read error  */
  292.    {
  293.       fprintf( stderr, "CRYP: read error no. %d\n", errno);
  294.       return( 11);
  295.    }
  296.  
  297.    fclose( stdin);                        /* Close files                 */
  298.    fclose( stdout);
  299.  
  300.    if( encipher)                          /* If encipher, open con. file */
  301.    {
  302.       if( (confile = fopen( "CRY.CON", "wb")) == NULL)
  303.       {
  304.      fprintf( stderr,
  305.         "CRYP: cannot open CRY.CON, error no. %d\n", errno);
  306.      return( 12);
  307.       }
  308.  
  309.       for( i = 0;  i < 9;  ++i)           /* Restore clear continuation  */
  310.      ri[i] = rc[i];                   /* seeds                       */
  311.  
  312.       for( i = POOLSIZE-1;  i >= 0;  --i) /* Build a random record     */
  313.      pool[i] = rc9();
  314.                       /* Write continuation file     */
  315.  
  316.       if( fwrite( pool, 1, CONSIZE, confile) != CONSIZE)
  317.       {
  318.      fprintf( stderr,
  319.         "CRYP: cannot write CRY.CON, error no. %d\n", errno);
  320.      return( 13);
  321.       }
  322.       fclose( confile);
  323.    }
  324.    return( 0);
  325. }                      /* End of term         */
  326.  
  327. /* --------------------------------------------------------------------- */
  328. void standard( char *cp)
  329. {
  330.     /*  Standardize a key string
  331.      *  Output characters are from 33 to 95 inclusive
  332.      */
  333.  
  334.    for(  ;  *cp;  ++cp)
  335.    {
  336.       *cp &= 127;
  337.  
  338.       if( *cp > 95)
  339.       *cp -= 32;
  340.  
  341.       if( *cp < 32)
  342.       *cp += 32;
  343.  
  344.       if( *cp == ' ')
  345.       *cp = '/';
  346.    }
  347. }                      /* End of standard         */
  348.  
  349. /* --------------------------------------------------------------------- */
  350. void convkey( void)
  351. {
  352.    /*  Convert the encryption key to 9 seeds
  353.     *
  354.     *  input: key[i], i = 0, ..., MAXKEY-1
  355.     *  output: rs[j], j = 0, ..., 8
  356.     *
  357.     *    [0]    [1]    [2]    [3]    [4]    [5]    [6]   ...  [22]   [23]
  358.     *  111111 111111 111111 111111 111111 111111 111111      111111 111111
  359.     *     6      6     4  2    6      6    2  4     6        6      6
  360.     *  ****** seed0 *****...... seed1 ......***** seed2  ...  seed8 ******
  361.     *         16 BITS           16 BITS         16 BITS     16 BITS
  362.     *
  363.     *  144 bit key converted to 144 bits of seed,
  364.     *  seeds of zero are changed to 1.
  365.     */
  366.  
  367.    int  i, j;
  368.    int  keyi[MAXKEY];         /* Key in integer form, 6 bits each int */
  369.  
  370.    for( i = 0;  i < MAXKEY;  ++i)
  371.       keyi[i] = key[i] & 63;
  372.  
  373.    for( i = 0, j = 0;  j < 9;  i += 8, j += 3)
  374.    {
  375.       rs[j]   =  ( keyi[i]   << 10) |
  376.          ( keyi[i+1] <<  4) |
  377.          ( keyi[i+2] >>  2);
  378.  
  379.       rs[j+1] =  ( keyi[i+2] << 14) |
  380.          ( keyi[i+3] <<  8) |
  381.          ( keyi[i+4] <<  2) |
  382.          ( keyi[i+5] >>  4);
  383.  
  384.       rs[j+2] =  ( keyi[i+5] << 12) |
  385.          ( keyi[i+6] <<  6) |
  386.            keyi[i+7];
  387.    }
  388.    for( j = 0;  j < 9;  ++j)          /* Do not allow a zero seed     */
  389.       if( !rs[j])
  390.      rs[j] = 1;
  391.  
  392.    for( i = 0;  i < MAXKEY;  ++i)
  393.       keyi[i] = 0;              /* Erase local key         */
  394.  
  395. }                      /* End of convkey         */
  396.  
  397. /* --------------------------------------------------------------------- */
  398. int rn( int n)
  399. {
  400.     /*
  401.      *  Returns the next random integer from ri[n], 0 <= n <= 8
  402.      */
  403.  
  404.    static int  repeat = TRUE;
  405.    int  i;
  406.  
  407.    switch( n)
  408.    {
  409.    case 0:
  410.  
  411.      /*  1st Congruential Generator, 16 bits
  412.       *  Generates Random integers from -32768 to 32767 inclusive
  413.       *  Cycle length = 65536 = 2**16
  414.       */
  415.  
  416.       return( ri[0] = 25173 * ri[0] + 6925);
  417.  
  418.    case 1:
  419.  
  420.      /*  1st Shift-register Generator, 16 bits
  421.       *  Random integer from -32768 to 32767 inclusive, 0 not generated
  422.       *  Generator = -22620, Cycle length = 65535 = 3 * 5 * 17 * 257
  423.       */
  424.  
  425.       if( ri[1] & 1)
  426.          return( ri[1] = ( (unsigned) ri[1] >> 1) ^ -22620);
  427.  
  428.       return( (unsigned) ri[1] >>= 1);
  429.  
  430.    case 2:
  431.  
  432.      /*  2nd Congruential Generator, 16 bits
  433.       *  Random integer from -32768 to 32767 inclusive
  434.       *  Cycle length = 65537 = prime, zero repeats once
  435.       */
  436.  
  437.       if( !ri[2])
  438.       {
  439.          if( repeat)
  440.          {
  441.         repeat = FALSE;
  442.         return( 0);
  443.          }
  444.          else repeat = TRUE;
  445.       }
  446.  
  447.       return( ri[2] = 23629 * ri[2] + 13849);
  448.  
  449.    case 3:
  450.  
  451.      /*  2nd Shift-register Generator, 16 bits
  452.       *  Random integer from -32768 to 32767, not all generated
  453.       *  Generator = -07493, Cycle length = 65521 = prime, (65536 - 15)
  454.       */
  455.  
  456.       if( ri[3] & 1)
  457.          ri[3] = ( (unsigned) ri[3] >> 1) ^ -7493;
  458.       else
  459.          (unsigned) ri[3] >>= 1;
  460.  
  461.       if( ri[3] == 1)
  462.          for( i = 0;  i < 14;  ++i)
  463.         rn( 3);              /* Throw 14 away         */
  464.  
  465.       return( ri[3]);
  466.  
  467.    case 4:
  468.  
  469.      /*  3rd Congruential Generator, 16 bits
  470.       *  Random integer from -32768 to 32767, not all generated
  471.       *  Cycle length = 65519 = prime, (65536 - 17)
  472.       */
  473.  
  474.       ri[4] = 4821 * ri[4] + 13001;
  475.       if( !ri[4])
  476.          for( i = 0;  i < 17;  ++i)
  477.         rn( 4);              /* Throw 17 away         */
  478.  
  479.       return( ri[4]);
  480.  
  481.    case 5:
  482.  
  483.      /*  3rd Shift-register Generator, 16 bits
  484.       *  Random integer from -32768 to 32767, not all generated
  485.       *  Generator = -25501, Cycle length = 65497 = prime, (65536 - 39)
  486.       */
  487.  
  488.       if( ri[5] & 1)
  489.          ri[5] = ( (unsigned) ri[5] >> 1) ^ -25501;
  490.       else
  491.          (unsigned) ri[5] >>= 1;
  492.  
  493.       if( ri[5] == 1)
  494.          for( i = 0;  i < 38;  ++i)
  495.         rn( 5);              /* Throw 38 away         */
  496.  
  497.       return( ri[5]);
  498.  
  499.    case 6:
  500.  
  501.      /*  4th Congruential Generator, 16 bits
  502.       *  Random integer from -32768 to 32767, not all generated
  503.       *  Cycle length = 65479 = prime, (65536 - 57)
  504.       */
  505.  
  506.       ri[6] = 10349 * ri[6] + 7001;
  507.       if( !ri[6])
  508.          for( i = 0;  i < 57;  ++i)
  509.         rn( 6);              /* Throw 57 away         */
  510.  
  511.       return( ri[6]);
  512.  
  513.    case 7:
  514.  
  515.      /*  4th Shift-register Generator, 16 bits
  516.       *  Random integer from -32768 to 32767, not all generated
  517.       *  Generator = -18916, Cycle length = 65449 = prime, (65536 - 87)
  518.       */
  519.  
  520.       if( ri[7] & 1)
  521.          ri[7] = ( (unsigned) ri[7] >> 1) ^ -18916;
  522.       else
  523.          (unsigned) ri[7] >>= 1;
  524.  
  525.       if( ri[7] == 1)
  526.          for( i = 0;  i < 86;  ++i)
  527.         rn( 7);              /* Throw 86 away         */
  528.  
  529.       return( ri[7]);
  530.  
  531.    case 8:
  532.  
  533.      /*  5th Congruential Generator, 16 bits
  534.       *  Random integer from -32768 to 32767, not all generated
  535.       *  Cycle length = 65447 = prime, (65536 - 89)
  536.       */
  537.  
  538.       ri[8] = 30133 * ri[8] + 14001;
  539.       if( !ri[8])
  540.          for( i = 0;  i < 89;  ++i)
  541.         rn( 8);              /* Throw 89 away         */
  542.  
  543.       return( ri[8]);
  544.    }
  545.    return( 0);                            /* This line is never reached  */
  546. }                      /* End of rn             */
  547.  
  548. /* --------------------------------------------------------------------- */
  549. int rc9( void)
  550. {
  551.     /*
  552.      *  Combination of rn(0) thru rn(8), one each
  553.      */
  554.  
  555.    int  i,  rc;
  556.  
  557.    for( rc = 0, i = 0;  i < 9;  ++i)
  558.       rc += rn( i);
  559.  
  560.    return( rc);
  561. }                      /* End of rc9             */
  562.  
  563. /* --------------------------------------------------------------------- */
  564. void erase( void)
  565. {
  566.     /*
  567.      *  Erase all trace of the encryption key
  568.      */
  569.  
  570.    int  i;
  571.  
  572.    for( i = 0;  i < MAXKEY;  ++i)
  573.       key[i] = 0;
  574.  
  575.    for( i = 0;  i < 9;  ++i)
  576.       ri[i] = rs[i] = 0;
  577.  
  578.    for( i = 0;  i < POOLSIZE;  ++i)
  579.       pool[i] = 0;
  580.  
  581.    rr = 0;
  582.  
  583. }                      /* End of erase         */
  584.                       /* End of CRYP.C         */
  585.